﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JAAF.Builders;
using JAAF.Builders.Configuration;
using System.Configuration;

namespace JAAF
{
    /// <summary>
    /// Provides concrete implementations for requested abstractions / interfaces
    /// </summary>
    /// 
    public static class ObjectFactory
    {

        #region Static Data

        /// <summary>
        /// Contains a dictionary of all the declared builders
        /// </summary>
        private static Dictionary<string, BuilderBase> s_dicBuilders = new Dictionary<string, BuilderBase>();

        private static ReflectionBuilder s_oBuilder;

        #endregion


        #region Initialization

        static ObjectFactory()
        {
            LoadConfiguration();
        }

        #endregion


        #region Methods

        public static object Create(string _sAbstraction, params object[] _aoConstructorParams)
        {
            return s_oBuilder.Create(_sAbstraction, _aoConstructorParams);
        }

        public static object Create(Type _oAbstractionType, params object[] _aoConstructorParams)
        {
            return s_oBuilder.Create(_oAbstractionType, _aoConstructorParams);
        }

        public static TAbstraction Create<TAbstraction>(params object[] _aoConstructorParams)
        {
            return s_oBuilder.Create<TAbstraction>(_aoConstructorParams);
        }

        /// <summary>
        /// Checks if an implementation for an abstraction is registered.
        /// </summary>
        /// <param name="_oAbstractionType">The <see cref="System.Type">type</see> of the abstraction.</param>
        /// <returns>True if an implementation is registered, otherwise false.</returns>
        public static bool IsRegistered(Type _oAbstractionType)
        {
            return s_oBuilder.IsRegistered(_oAbstractionType);
        }

        /// <summary>
        /// Checks if an implementation for an abstraction is registered with this builder
        /// </summary>
        /// <param name="_sAbstractionName">The name of the abstraction</param>
        /// <returns>True if an implementation is registered, otherwise false.</returns>
        public static bool IsRegistered(string _sAbstraction)
        {
            return s_oBuilder.IsRegistered(_sAbstraction);
        }

        /// <summary>
        /// Loads the configuration into the default builder
        /// </summary>
        private static void LoadConfiguration()
        {

            s_oBuilder = new ReflectionBuilder();

            BuildersConfigurationSection oSection = BuildersConfigurationSection.Current;
            if (oSection == null)
                return;

            try
            {
                foreach (ImplementationRegistration oReg in oSection.Implementations)
                {
                    s_oBuilder.RegisterImplementation(oReg.Abstraction, oReg.ImplementationTypeName, oReg.InstancingPolicy);
                }
            }

            catch (Exception ex)
            {
                throw new ConfigurationErrorsException("An exception was thrown while reading the JAAF Builders configuration section", ex);
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// Provides access to the <see cref="BuilderBase">builder</see>
        /// used by the object factory.
        /// </summary>
        public static BuilderBase Builder
        {
            get
            {
                return s_oBuilder;
            }
        }

        #endregion

    }
}
